%       jianpu.sty      coded by YIN Dian
%       Typeset Chinese Numbered Musical Notation.
%       Hist:   080124  Start coding.
%               080125  Continue coding.
%               080201  Continue coding.
%               080203  Continue coding.
%               080211  Continue coding.
%               080212  Continue coding.
\NeedsTeXFormat{LaTeX2e}[1996/12/01]
\def\fileversion{0.1}
\def\filedate{2008/02/01}
\ProvidesPackage{jianpu}[\filedate\space\fileversion]

\ifx\eTeXrevision\@undefined
  \PackageError{jianpu}{eTeX required to use this package}{}
\fi

% allocation
\newif\ifjpu@result
\newbox\jpu@tmpbox
\newdimen\jpu@tmpdim
\newcount\jpu@tmpcnt
\newcount\jpu@notelen
\newcount\jpu@lastnotelen
\newcount\jpu@tabindex
\newtoks\jpu@line

% parameter setting
\def\jpu@p@notewidth{1em}
\def\jpu@p@rulesep{0.8pt}
\def\jpu@p@ruleheight{0.4pt}
\def\jpu@p@intermeasuresep{0.5em}
\def\jpu@p@font{\sffamily}
\def\jpu@p@vbarrule{\vrule\@height.7\baselineskip\@depth.3\baselineskip\@width.4pt}

% \futurenonspacelet
\def\@BTcs{}
\let\nexttoken\relax
\let\next\relax
\def\futurenonspacelet#1{\def\@BTcs{#1}%
   \afterassignment\@BTfnslone\let\nexttoken= }
\def\@BTfnslone{\expandafter\futurelet\@BTcs\@BTfnsltwo}
\def\@BTfnsltwo{\expandafter\ifx\@BTcs\@sptoken\let\next=\@BTfnslthree
   \else\let\next=\nexttoken\fi \next}
\def\@BTfnslthree{\afterassignment\@BTfnslone\let\next= }

% some basic macros
\def\jpu@firsttok#1#2\@nil{#1}
\def\jpu@testifnum#1{%
  \jpu@resultfalse
  \def\jpu@tmpmacro{#1}%
  \unless\ifx\jpu@tmpmacro\empty
    \expandafter\def\expandafter\jpu@tmpmacr@\expandafter{\jpu@firsttok #1\@nil}%
    \ifx\jpu@tmpmacro\jpu@tmpmacr@
      \if\noexpand #10\jpu@resulttrue\else
      \if\noexpand #11\jpu@resulttrue\else
      \if\noexpand #12\jpu@resulttrue\else
      \if\noexpand #13\jpu@resulttrue\else
      \if\noexpand #14\jpu@resulttrue\else
      \if\noexpand #15\jpu@resulttrue\else
      \if\noexpand #16\jpu@resulttrue\else
      \if\noexpand #17\jpu@resulttrue\else
      \if\noexpand #18\jpu@resulttrue\else
      \if\noexpand #19\jpu@resulttrue\else
      \if\noexpand #1&\jpu@resulttrue % place holder
      \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
    \fi
  \fi
}

\def\jpu@print{\immediate\write16}

% jpuline part
\def\jpu@state{0}

\def\jpu@addtoline#1{%
  \edef\abc{\the\jpu@line}%
  \jpu@print{\meaning\abc}%
  \edef\do{\jpu@line={\the\jpu@line #1}}%
  \do
}
% macros that are used in \jpu@addtoline should be defined with \protected

\def\jpntld{\ifnum\jpu@notelen>0 \expandafter\jpu@ntld\fi}
\def\jpntld@{% use the smaller one as leader
  \ifnum\jpu@lastnotelen>0 
    \ifnum\jpu@lastnotelen<\jpu@notelen
      \expandafter\expandafter\expandafter\jpu@ntld@
      \expandafter
    \else
      \unless\ifnum\jpu@notelen>0 
        \jpu@ntld@gobblefi
      \fi
      \expandafter\expandafter\expandafter\jpu@ntld
      \expandafter
    \fi
  \fi
}
\def\jpu@ntld{\expandafter\jpu@noteleader\expandafter{\the\jpu@notelen}}
\def\jpu@ntld@{\expandafter\jpu@noteleader\expandafter{\the\jpu@lastnotelen}}
\def\jpu@ntld@gobblefi\fi#1\fi{\fi\fi}

\protected\def\jpu@noteleader#1{% #1: number of underlines (i.e. note length)
  \jpu@tmpcnt=#1%
  \setbox0=\hb@xt@ 0.1pt{\vphantom{\jpu@p@font 0}\hss}%
  \jpu@addboxul
  \cleaders\box0
}

\def\jpu@addboxul{% \jpu@tmpcnt and \box0 should be pre-set
  \loop
  \ifnum\jpu@tmpcnt>0
    %\setbox0=\hbox{$\m@th\@@underline{\box0}$}%
    \setbox0=\hbox{\vtop{\box0\vskip\jpu@p@rulesep\hrule\@height\jpu@p@ruleheight}}%
    \advance\jpu@tmpcnt-1
  \repeat
}

\protected\def\jpu@shownote#1#2{% #1: note name, #2: note length
  \jpu@tmpcnt=#2%
  \setbox0=\hbox{\jpu@p@font #1}%
  \jpu@addboxul
  \box0
}

\def\jpuline{%
  \begingroup
  \def\jpu@lines{}%
}
\def\endjpuline{%
  \ialign{&##\hfil\cr
    \jpu@lines
  }%
  \begingroup
  \par
  \ttfamily
  \meaning\jpu@lines
  \par
  \endgroup
  \endgroup
}

\def\melody{\jpu@melody}
\def\jpu@melody{%
  \jpu@line={}%
  \jpu@lastnotelen=0
  \jpu@notelen=0
  \jpu@tabindex=0
  \let\jpu@notename\empty
  \def\jpu@noteextr{}%
  \futurenonspacelet\jpu@nextchar\jpu@melody@iter
}

\def\jpu@melody@iter{%
  \def\jpu@return{\futurenonspacelet\jpu@nextchar\jpu@melody@iter}%
  \def\jpu@iternext{\afterassignment\jpu@return\let\jpu@nextchar}%
  \ifx\jpu@nextchar\bgroup % next char is {
    \let\jpu@iternext\jpu@melody@addnextgroup
  \else
    \jpu@testifnum\jpu@nextchar
    \ifjpu@result       % next char is a number
      \let\jpu@iternext\jpu@melody@numbernext
    \else
      \ifx\jpu@nextchar|% bar line
        \let\jpu@iternext\jpu@melody@bar
      \else
        \ifx\jpu@nextchar[% halve note length
          \jpu@melody@flushnote
          \jpu@melody@flushnote
          \advance\jpu@notelen 1
        \else
          \ifx\jpu@nextchar]% double note length
            \unless\ifx\jpu@notename\relax % note not outputed
              \jpu@melody@flushnote
            \fi
            \advance\jpu@notelen-1
            \jpu@lastnotelen=\jpu@notelen
            \ifnum\jpu@notelen<0
              \PackageError{jianpu}{Note length cannot double now.}{}
            \fi
          \else
            \ifx\jpu@nextchar(% begin tie
              \let\jpu@iternext\jpu@melody@begintie
            \else
              \ifx\jpu@nextchar)% end tie
                \let\jpu@iternext\jpu@melody@endtie
              \else
                \ifx\jpu@nextchar\\% end of \melody line
                  \let\jpu@iternext\jpu@endmelody
                \else
                  \let\jpu@iternext\jpu@melody@addnextchar
                \fi
              \fi
            \fi
          \fi
        \fi
      \fi
    \fi
  \fi
  \jpu@iternext
}

\def\jpu@melody@addnextgroup#1{%
  \jpu@line=\expandafter{\the\jpu@line {#1}}%
  \jpu@return
}

\def\jpu@melody@addnextchar#1{%
  \jpu@line=\expandafter{\the\jpu@line #1}%
  \jpu@return
}

\def\jpu@melody@numbernext#1{% #1: number, i.e. the musical note
  \jpu@print{Next is number #1. \the\jpu@line}%
  \jpu@melody@flushnote
  \jpu@melody@flushnote
  \jpu@line=\expandafter{\the\jpu@line &}%
  \def\jpu@notename{#1}%
  \def\jpu@noteextr{}%
  \futurenonspacelet\jpu@nextchar\jpu@melody@numberextra
}

\def\jpu@melody@numberextra{% ^ _ - . etc
  \let\jpu@melody@numberextranext\jpu@return
  \ifx\jpu@nextchar^%
    \let\jpu@melody@numberextranext\jpu@melody@numberextreat
  \else
    \ifx\jpu@nextchar_%
      \let\jpu@melody@numberextranext\jpu@melody@numberextreat
    \else
      \ifx\jpu@nextchar-%
        \let\jpu@melody@numberextranext\jpu@melody@numberextreat
      \else
        \ifx\jpu@nextchar.%
          \let\jpu@melody@numberextranext\jpu@melody@numberextreat
        \fi
      \fi
    \fi
  \fi
  \jpu@melody@numberextranext
}

\def\jpu@melody@numberextreat#1{%
  \expandafter\def\expandafter\jpu@noteextr\expandafter{\jpu@noteextr #1}%
  \futurenonspacelet\jpu@nextchar\jpu@melody@numberextra
}

\def\jpu@melody@flushnote{%
  \unless\ifx\jpu@notename\empty
    \ifx\jpu@notename\relax % note outputed, but right space not
      \jpu@print{right space output}%
      \jpu@addtoline{\jpntld\hskip\the\jpu@tmpdim\relax}%
      \let\jpu@notename\empty
      \jpu@print{right space output ended}%
    \else % note not outputed
      \jpu@print{note output \jpu@notename}%
      \if &\jpu@notename % place holder
        \setbox\jpu@tmpbox=\hbox{\vphantom{\jpu@p@font 0}}%
      \else
        \setbox\jpu@tmpbox=\hbox{\jpu@p@font\jpu@notename}%
      \fi
      \jpu@tmpdim=\dimexpr(\jpu@p@notewidth-\wd\jpu@tmpbox)/2
      \jpu@addtoline{\jpntld@\hskip\the\jpu@tmpdim\relax}%
      %\jpu@addtoline{\llap{${}^{\the\jpu@notelen}_{\the\jpu@lastnotelen}$}}%
      \unless\if &\jpu@notename % place holder
        \jpu@addtoline{\jpu@shownote{\jpu@notename}{\the\jpu@notelen}}%
      \fi
      \let\jpu@notename\relax
      \jpu@lastnotelen=\jpu@notelen
      \jpu@print{note output ended}%
    \fi
  \fi
}

\def\jpu@melody@begintie({%
  \jpu@return
}

\def\jpu@melody@endtie){%
  \jpu@return
}

\def\jpu@melody@bar|{%
  \jpu@print{Bar, end measure}%
  \jpu@lastnotelen=\jpu@notelen
  \jpu@melody@flushnote
  \jpu@melody@flushnote
  \jpu@line=\expandafter{\the\jpu@line&\hb@xt@\z@{\hss\jpu@p@vbarrule\hss}}%
  \jpu@return
}

\def\jpu@stripamp&#1\@nil{#1}

\def\jpu@endmelody\\{%
  \jpu@melody@flushnote
  \jpu@melody@flushnote
  \def\jpu@tmpmacro{&}%
  \edef\jpu@tmpmacr@{\expandafter\jpu@firsttok\the\jpu@line\@nil}%
  \ifx\jpu@tmpmacro\jpu@tmpmacr@
    \edef\do{\expandafter\jpu@stripamp\the\jpu@line\@nil}%
    \jpu@line=\expandafter{\do}%
  \fi
  \edef\abc{\the\jpu@line}%
  \message{\meaning\abc}%
  \toks0=\expandafter{\jpu@lines}%
  \edef\do{\def\noexpand\jpu@lines{\the\toks0\the\jpu@line\tabskip=\z@\crcr}}%
  \do
}


\endinput
